package com.googlecode.grt192.HH11.deploy;

import com.googlecode.grt192.HH11.actuator.ISolenoid;
import com.googlecode.grt192.HH11.actuator.PneumaticActuatorDisplay;
import com.googlecode.grt192.HH11.controller.HHController;
import com.googlecode.grt192.HH11.mechanism.HHMechanism;
import com.googlecode.grt192.HH11.sensor.HHSafety;
import com.googlecode.grt192.HH11.sensor.HHToggleSwitch;
import com.googlecode.grt192.HH11.sensor.IHHSwitch;
import com.googlecode.grt192.HH11.sensor.SwitchDisplay;
import com.googlecode.grtframework.rpc.RPCConnection;
import com.googlecode.grtframework.sensor.ISwitch;
import com.googlecode.grtframework.vis.Displayer;

/**
 * A HauntedHouse controls a set of linear actuators.
 * 
 * The HauntedHouse can simulate and visualize all components.
 * 
 * Actuators are always visualized.
 * 
 * Switches can be selected for simulation but switching between switches
 * shouldn't require rerun of code things that listen to them will
 * 
 * Switches are always visualized.
 * 
 * @author ajc
 * 
 */
public class HauntedHouse {

	private final String crioAddress;
	private final int crioPort;
	private final String usbPort;
	private final int masterRPCKey;
	private final int autoRPCKey;
	private final int[] switchRPCKeys;
	private final int[] actuatorRPCkeys;
	private final int numMechs;

	RPCConnection crioRPC;
	RPCConnection spotRPC;

	Displayer houseDisplay;
	// JFrame house;

	Displayer switchDisplay;
	// JFrame switches;

	ISwitch masterButtonSim;
	ISwitch masterButtonRPC;
	SwitchDisplay masterButtonDisplay;

	ISwitch autoButtonSim;
	ISwitch autoButtonRPC;
	SwitchDisplay autoButtonDisplay;

	ISwitch[] switchSims;
	ISwitch[] switchRPCs;
	SwitchDisplay[] switchDisplays;

	PneumaticActuatorDisplay[] actuatorSims;
	ISolenoid[] actuatorRPCs;

	HHSafety safetyButton;

	IHHSwitch[] switches;

	HHMechanism[] mechanisms;

	HHController[] controllers;

	public HauntedHouse(String crioAddress, int crioPort, String usbPort,
			Displayer houseDisplay, Displayer switchDisplay,
			ISwitch masterButtonSim, int masterRPCKey,
			SwitchDisplay masterButtonDisplay, ISwitch autoButtonSim,
			int autoRPCKey, SwitchDisplay autoButtonDisplay,
			ISwitch[] switchSims, SwitchDisplay[] switchDisplays,
			int[] switchRPCKeys, PneumaticActuatorDisplay[] actuatorSims,
			int[] actuatorRPCkeys, int numMechs, int[][] waitTimes) {
		this.crioAddress = crioAddress;
		this.crioPort = crioPort;
		this.usbPort = usbPort;
		this.houseDisplay = houseDisplay;
		this.switchDisplay = switchDisplay;
		this.masterButtonSim = masterButtonSim;
		this.masterRPCKey = masterRPCKey;
		this.autoRPCKey = autoRPCKey;
		this.switchRPCKeys = switchRPCKeys;
		this.actuatorRPCkeys = actuatorRPCkeys;
		this.numMechs = numMechs;
		// this.masterButtonRPC = masterButtonRPC;
		this.masterButtonDisplay = masterButtonDisplay;
		this.autoButtonSim = autoButtonSim;
		// this.autoButtonRPC = autoButtonRPC;
		this.autoButtonDisplay = autoButtonDisplay;
		this.switchSims = switchSims;
		// this.switchRPCs = switchRPCs;
		this.switchDisplays = switchDisplays;
		this.actuatorSims = actuatorSims;
		// this.actuatorRPCs = actuatorRPCs;
		// this.safetyButton = safetyButton;
		// this.mechanisms = mechanisms;
		// this.controllers = controllers;

		safetyButton = new HHSafety(masterButtonSim);

		switches = new IHHSwitch[numMechs];
		mechanisms = new HHMechanism[numMechs];
		controllers = new HHController[numMechs];
		for (int i = 0; i < numMechs; i++) {
			switches[i] = new HHToggleSwitch(autoButtonSim, switchSims[i]);

			mechanisms[i] = new HHMechanism(
					new ISolenoid[] { this.actuatorSims[i] }, safetyButton);
			// safetyButton.addSafetyListener(mechanisms[i]);

			controllers[i] = new HHController(mechanisms[i], switches[i],
					waitTimes[i]);
		}
	}

	public void start() {
		houseDisplay.startPaintLoop();
		switchDisplay.startPaintLoop();
	}

	/**
	 * Convert all control to simulated switches
	 */
	public void useSimSwitches() {
		// enable sim switches (start listening)

		// disable rpc switches (stop listening)

		// all listeners: stop listening
		// all listeners: set switch to the other type of switch
		// all listeners: restart listening

		//
		masterButtonSim.start();
		masterButtonDisplay.startListening();
		switchDisplay.addDisplayable(masterButtonDisplay);
		//
		autoButtonSim.start();
		autoButtonDisplay.startListening();
		switchDisplay.addDisplayable(autoButtonDisplay);
		//
		// switchSims[0].start();
		for (int i = 0; i < numMechs; i++) {
			switchSims[i].start();
			switchDisplays[i].startListening();
			switchDisplay.addDisplayable(switchDisplays[i]);
		}
		for (int i = 0; i < numMechs; i++) {
			actuatorSims[i].start();// TODO actuator interface
			houseDisplay.addDisplayable(actuatorSims[i]);
		}

		safetyButton.startListening();

		for (int i = 0; i < numMechs; i++) {
			switches[i].startListening();
			mechanisms[i].startListening();
			controllers[i].startListening();
		}

	}

	public void useRPCSwitches() {

	}

}
